package cool.mtc.minghe.service.service.sys.user.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cool.mtc.core.exception.ServiceException;
import cool.mtc.core.page.PageData;
import cool.mtc.core.util.CollectionUtil;
import cool.mtc.minghe.data.entity.sys.user.UserDO;
import cool.mtc.minghe.data.entity.sys.user.UserOrgRoleDO;
import cool.mtc.minghe.data.model.sys.user.dto.UserDTO;
import cool.mtc.minghe.data.model.sys.user.dto.UserDetailDTO;
import cool.mtc.minghe.data.model.sys.user.dto.UserListDTO;
import cool.mtc.minghe.data.model.sys.user.dto.UserOrgRoleDTO;
import cool.mtc.minghe.data.model.sys.user.form.UserForm;
import cool.mtc.minghe.data.model.sys.user.query.UserQuery;
import cool.mtc.minghe.service.manager.sys.user.UserManager;
import cool.mtc.minghe.service.mapper.sys.user.UserMapper;
import cool.mtc.minghe.service.mapper.sys.user.UserOrgRoleMapper;
import cool.mtc.minghe.service.service.BaseServiceImpl;
import cool.mtc.minghe.service.service.sys.user.UserOrgRoleService;
import cool.mtc.minghe.service.service.sys.user.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author 明河
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserServiceImpl extends BaseServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final UserManager userManager;
    private final UserOrgRoleMapper userOrgRoleMapper;

    private final UserOrgRoleService userOrgRoleService;

    @Override
    @Transactional
    public long insert(UserForm form) {
        UserDO userDO = form.transToDO();
        userDO.setCreator(userId());
        super.handleCheckDictExist(form.getStatusDictId(), "dict.type.user_status");
        // TODO: 2022-01-06 检查单位信息是否存在
        userMapper.insert(userDO);
        // 增加用户-单位-角色关联关系
        List<UserOrgRoleDO> userOrgRoleDOList = form.transToUserOrgRoleDO(userDO.getId());
        userOrgRoleService.update(userDO.getId(), userOrgRoleDOList);
        return userDO.getId();
    }

    @Override
    @Transactional
    public void update(UserForm form) {
        UserDO userDO = userMapper.selectById(form.getId());
        if (null == userDO) {
            throw new ServiceException("data.expired");
        }
        form.updateDO(userDO);
        userMapper.updateById(userDO);
        // 更新用户-单位-角色关联关系
        List<UserOrgRoleDO> userOrgRoleDOList = form.transToUserOrgRoleDO(userDO.getId());
        userOrgRoleService.update(form.getId(), userOrgRoleDOList);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        if (null == id) {
            return;
        }
        UserDO userDO = userMapper.selectById(id);
        if (null == userDO) {
            return;
        }
        this.handleCheckCanDelete(userDO);
        userMapper.deleteById(id);
    }

    /**
     * 检查是否可以删除
     */
    private void handleCheckCanDelete(UserDO userDO) {
        // TODO 检查是否可以删除
    }

    @Override
    public PageData<UserListDTO> pageList(UserQuery query) {
        OrderItem[] items = {
                OrderItem.asc("O.order_index"),
                OrderItem.asc("U.create_time"),
        };
        Page<UserListDTO> page = userMapper.pageList(super.pageParam(items), query);
        return PageData.of(page.getRecords(), page.getTotal());
    }

    @Override
    public UserDTO info(Long id) {
        if (null == id) {
            return null;
        }
        UserDTO userDTO = userMapper.getById(id);
        List<UserOrgRoleDTO> userOrgRoleDTOList = userOrgRoleMapper.listOrgRoleByUserId(id);
        this.handleUserOrgRoleData(userDTO, userOrgRoleDTOList);
        return userDTO;
    }

    private void handleUserOrgRoleData(UserDTO user, List<UserOrgRoleDTO> userOrgRoleList) {
        if (CollectionUtil.isEmpty(userOrgRoleList)) {
            return;
        }
        List<UserOrgRoleDTO> userOrgList = new ArrayList<>();
        userOrgRoleList.forEach(userOrgRole -> {
            Optional<UserOrgRoleDTO> optional = userOrgList.stream().filter(userOrg -> userOrg.getOrgId().equals(userOrgRole.getOrgId())).findFirst();
            if (optional.isPresent()) {
                Optional.ofNullable(userOrgRole.getRoleId()).ifPresent(roleId -> optional.get().getRoleIdList().add(roleId));
            } else {
                UserOrgRoleDTO item = new UserOrgRoleDTO();
                item.setOrgId(userOrgRole.getOrgId());
                item.setOrgName(userOrgRole.getOrgName());
                Optional.ofNullable(userOrgRole.getRoleId()).ifPresent(roleId -> item.getRoleIdList().add(roleId));
                userOrgList.add(item);
            }
        });
        user.setUserOrgList(userOrgList);
    }

    @Override
    public UserDetailDTO current() {
        return userManager.getUserDetailByUserIdAndOrgId(userId(), orgId());
    }
}
